#include <nxos.h>

NX_PRIVATE volatile int oneShotFlag;

NX_PRIVATE void TimerHandler0(void * arg)
{
    NX_Printf("timer handler: arg %p\n", arg);
    oneShotFlag = 2;
}

NX_PRIVATE void TestTimerOneShot(NX_U32 millisecond)
{
    NX_Printf("test timer one shot %d ms start\n", millisecond);

    oneShotFlag = 1;

    NX_Solt timer0;
    timer0 = NX_TimerCreate(millisecond, TimerHandler0, (void *)0x1234abcd, NX_TIMER_ONESHOT);
    if (timer0 == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("create timer failed!\n");
        return;
    }
    NX_TimerStart(timer0);

    while (oneShotFlag != 2)
    {
        /* code */
    }
    
    NX_Printf("test timer one shot %d ms done\n", millisecond);
}

NX_PRIVATE void TestTimerOneShotAutoStart(NX_U32 millisecond)
{
    NX_Printf("test timer one shot auto start %d ms start\n", millisecond);

    oneShotFlag = 1;

    NX_Solt timer0;
    timer0 = NX_TimerCreate(millisecond, TimerHandler0, (void *)0x1234abcd, NX_TIMER_ONESHOT | NX_TIMER_CREATE_START);
    if (timer0 == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("create timer failed!\n");
        return;
    }

    while (oneShotFlag != 2)
    {
        /* code */
    }
    
    NX_Printf("test timer one shot auto start %d ms done\n", millisecond);
}

NX_PRIVATE volatile int periodFlag;

NX_PRIVATE void TimerHandler1(void * arg)
{
    NX_Printf("timer handler: arg %p\n", arg);
    periodFlag++;
}

NX_PRIVATE void TestTimerPeriod(NX_U32 millisecond)
{
    NX_Printf("test timer period %d ms start\n", millisecond);

    periodFlag = 1;

    NX_Solt timer0;
    timer0 = NX_TimerCreate(millisecond, TimerHandler1, (void *)0x1234abcd, NX_TIMER_PERIOD);
    if (timer0 == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("create timer failed!\n");
        return;
    }
    NX_TimerStart(timer0);

    while (1)
    {
        if (periodFlag > 10)
        {
            NX_TimerStop(timer0);
            break;
        }
    }
    
    NX_Printf("test timer period %d ms done\n", millisecond);
}

NX_Error TEST_Timer(char *cmdline)
{
    int i;
    for (i = 1; i < 10000; i *= 5)
    {
        TestTimerOneShot(i);
        TestTimerOneShotAutoStart(i);
    }

    for (i = 1; i < 10000; i *= 5)
    {
        TestTimerPeriod(i);
    }
    
    return NX_EOK;
}
